package slave

import (
	"fmt"
	"iec61850/device"
	"iec61850/model"
	"iec61850/protocol"
)

type Slave struct {
	devices []device.Device
	server  *protocol.IEC61850Server
}

func NewSlave() *Slave {
	return &Slave{
		devices: make([]device.Device, 0),
		server:  protocol.NewIEC61850Server(),
	}
}

func (s *Slave) AddDevice(dev device.Device) {
	s.devices = append(s.devices, dev)
	s.registerDevice(dev)
}

func (s *Slave) registerDevice(dev device.Device) {
	logicalDevice := protocol.NewLogicalDevice(dev.GetLogicalDeviceName())

	for nodeName, nodeData := range dev.GetLogicalNodes() {
		logicalNode := protocol.NewLogicalNode(nodeName)
		for dataName, dataValue := range nodeData.(map[string]interface{}) {
			logicalNode.AddDataObject(dataName, protocol.MX, dataValue)
		}
		logicalDevice.AddLogicalNode(logicalNode)
	}

	s.server.AddLogicalDevice(logicalDevice)
}

func (s *Slave) Start(addr string) error {
	return s.server.Start(addr)
}

func (s *Slave) GetAttributes() []model.DeviceAttribute {
	attributes := make([]model.DeviceAttribute, 0)
	for _, device := range s.devices {
		attributes = append(attributes, device.GetAttributes()...)
	}
	return attributes
}

func (s *Slave) ExecuteOperation(name string) error {
	for _, device := range s.devices {
		for _, op := range device.GetOperations() {
			if op.Name == name {
				return op.Func()
			}
		}
	}
	return fmt.Errorf("operation not found")
}

type Request struct {
	Action    string
	Operation string
}

type Response struct {
	Success bool
	Error   string
}
